﻿using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using System.Diagnostics;

namespace Gateway.OpenTelemetry
{
    /// <summary>
    /// OpenTelemetry service collection extension
    /// </summary>
    public static class OpenTelemetryServiceCollectionExtension
    {
        /// <summary>
        /// 配置 OpenTelemetry
        /// </summary>
        /// <param name="builder"></param>
        public static void ConfigureOpenTelemetry(this WebApplicationBuilder builder)
        {
            OpenTelemetryOption options = null;
            {
                // 先读取 字符串的数据 如果字符串没有，那么再读取 section 的数据
                var option = builder.Configuration["OpenTelemetry_Option"];
                if (option != null)
                {
                    options = JsonConvert.DeserializeObject<OpenTelemetryOption>(option);
                }
                if (options == null)
                {
                    options = builder.Configuration.GetSection("OpenTelemetry").Get<OpenTelemetryOption>();
                }
            }
            if (options == null)
            {
                Debug.WriteLine("未获取到 OpenTelemetry_Option 或者 OpenTelemetry 配置的内容，不进行设置 OpenTelemetry ");
                return;
            }
            if (!options.Enable)
            {
                return;
            }
            builder.Logging.AddOpenTelemetry(logging =>
            logging.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(options.ServiceName))
                .AddOtlpExporter(o =>
                {
                    o.Endpoint = new Uri(options.Endpoint);
                }));
            builder.Services
                        .AddOpenTelemetry()
                        .ConfigureResource(b => b
                            .AddService(serviceName: options.ServiceName, serviceInstanceId: Environment.MachineName))
                        .WithTracing(b => b
                            .SetSampler(new AlwaysOnSampler())
                            .AddEntityFrameworkCoreInstrumentation(options => options.SetDbStatementForText = true)
                            .AddHttpClientInstrumentation()
                            .AddAspNetCoreInstrumentation(options =>
                            {
                                options.RecordException = true;
                            })
                            .AddOtlpExporter(o =>
                            {
                                o.Endpoint = new Uri(options.Endpoint);
                            })
                        )
                        .WithMetrics(b => b
                            .AddRuntimeInstrumentation()
                            .AddAspNetCoreInstrumentation()
                            .AddOtlpExporter(o =>
                            {
                                o.Endpoint = new Uri(options.Endpoint);
                            })
                        );

        }
    }
}
